package de.hauschild.gmltracer.gml.impl.value.geometry;

import de.hauschild.gmltracer.gml.Interpreter;
import de.hauschild.gmltracer.gml.TokenStack;
import de.hauschild.gmltracer.gml.impl.GmlInterpreter;
import de.hauschild.gmltracer.gml.impl.control.FunctionToken;
import de.hauschild.gmltracer.gml.impl.value.integer.IntegerToken;
import de.hauschild.gmltracer.gml.impl.value.real.RealToken;
import de.hauschild.gmltracer.tracer.SurfaceFunction;
import de.hauschild.gmltracer.tracer.SurfaceProperties;

/**
 * A implementation of {@link SurfaceFunction} using GML to calculate the
 * {@link SurfaceProperties}.
 * 
 * @author Klaus Hauschild
 * @since 1.0.0
 */
public class GmlSurfaceFunction implements SurfaceFunction {

  private final static Interpreter GML_INTERPRETER = new GmlInterpreter();

  private final FunctionToken surfaceFunction;

  /**
   * Instantiates a new GML surface function.
   * 
   * @param theSurfaceFunction
   *          the surface function
   */
  public GmlSurfaceFunction(final FunctionToken theSurfaceFunction) {
    surfaceFunction = theSurfaceFunction;
  }

  @SuppressWarnings("boxing")
  @Override
  public SurfaceProperties apply(final int face, final double u, final double v) {
    final TokenStack tokenStack = new TokenStack();

    tokenStack.push(new IntegerToken(face));
    tokenStack.push(new RealToken(u));
    tokenStack.push(new RealToken(v));

    GML_INTERPRETER.interpret(surfaceFunction.getEnvironment(), tokenStack, surfaceFunction.getTokenList());

    return new GmlSurfaceProperties(tokenStack);
  }

}
